<!--发帖用文本框-->
<script setup>
import {ref, toRefs, watch} from "vue";
import {Codemirror} from "vue-codemirror";
import {autocompletion} from "@codemirror/autocomplete";
import {EditorSelection} from "@codemirror/state";
import {setupMapState} from "@/assets/js/vuexUtils";
import {bbsCodeCompletion, matcherFactory} from "@/assets/js/autoCompletion";
import {EditorView} from "@codemirror/view";
import {ElementUtils} from "@/assets/js/ElementUtils";

const props = defineProps({
  modelValue: {type: String},
})
const emit = defineEmits(['update:modelValue', 'pastedFile'])
const {modelValue} = toRefs(props)
// 正文
const content = ref(modelValue.value);
// 代码自动完成数据 start
const {emotesCompletion} = setupMapState("Resources", ['emotesCompletion']);
const {fontColorCompletion} = setupMapState("Resources", ['fontColorCompletion']);
const {fontSizeCompletion} = setupMapState("Resources", ['fontSizeCompletion']);
const {fontsCompletion} = setupMapState("Resources", ['fontsCompletion']);
const {customEmotesCompletion} = setupMapState("Resources", ['customEmotesCompletion']);
// 代码自动完成数据 end

// codemirror对象
let view;
const editor = ref();

// 文本框准备好了
const handleReady = (payload) => {
  view = payload.view;

  // 准备好之后把光标移动到末尾
  if (content.value) {
    view.dispatch({
      selection: EditorSelection.cursor(content.value.length)
    })
  }
}

const init = (text) => content.value = text;

const replace = (target, replacement) => {
  content.value = content.value.replace(target, replacement)
}

/**
 * 向当前光标位置插入文本
 * @param text 文本
 */
const insertText = (text) => {
  if (text) {
    view.dispatch(view.state.replaceSelection(text))
  }
  view.focus()
}
/**
 * 把当前选中位置用前后缀包裹
 * @param prefix 前缀
 * @param suffix 后缀
 */
const bracket = (prefix = "", suffix = "") => {
  const {from, to} = view.state.selection.ranges[0]
  // 插入后缀
  view.dispatch({
    changes: {from: to, to, insert: suffix}
  })
  // 插入前缀 选中中间
  view.dispatch({
    changes: {from, to: from, insert: prefix},
    selection: EditorSelection.range(from + prefix.length, to + prefix.length)
  })
  setTimeout(() => view.focus(), 500)
}
// 自动完成提示
const autoCompletion = [
  //   论坛代码提示:字体颜色
  matcherFactory(/\[[\w=]*/, fontColorCompletion.value),
  //   论坛代码提示:字体大小
  matcherFactory(/\[[\w=]*/, fontSizeCompletion.value),
  //   论坛代码提示:字体
  matcherFactory(/\[[\w=]*/, fontsCompletion.value),
  //   论坛代码提示:其他常用代码
  matcherFactory(/\[[\w=]*/, bbsCodeCompletion),
  //   表情提示
  matcherFactory(/@[^@]*/, emotesCompletion.value),
  //   自定义表情提示
  matcherFactory(/#[^#]*/, customEmotesCompletion.value),
]

// 允许的后缀
const extension = ['zip', 'mp3', 'mp4']

const onPaste = (e) => {
  // console.log(e)
  const {clipboardData} = e
  const {files, items} = clipboardData
  if (clipboardData && clipboardData.files) {
    const uploadFiles = [...files]
    // console.log(files)

    const getExtension = (file) => file.name.substring(file.name.lastIndexOf('.') + 1)
    // 文件类型校验
    const illegalFile = uploadFiles.filter(file => !file.type.startsWith('image/') && !extension.includes(getExtension(file)))
    if (illegalFile.length > 0) {
      console.log(illegalFile)
      ElementUtils.notice({message: `只能上传图片及以下后缀文件:  ` + extension.join("， "), type: 'warning'})
      return;
    }
    if (uploadFiles.length > 0) {
      emit('pastedFile', uploadFiles)
    }
  }
}

watch(content, (nv) => {
  emit("update:modelValue", nv);
})


defineExpose({
  insertText, bracket, replace, init
})

</script>

<template>
  <div style="background-color: white">
    <codemirror
        v-model="content"
        :extensions="[autocompletion({override:autoCompletion}),EditorView.lineWrapping]"
        autofocus
        :placeholder="'请输入正文内容, 字数过少时会自动添加字数补丁\n\n\n'"
        @ready="handleReady"
        @paste="onPaste"
    />
  </div>
</template>

<style scoped>

</style>